package com.xhs.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;

/**
 * @desc: CompletableFuture 多任务组合回调
 * @projectName: java-tools-parent
 * @author: xhs
 * @date: 2025-08-09 周六 16:10
 */
@Slf4j
@RestController
@RequestMapping("/completableFuture3")
public class CompletableFuture3Controller {

    @Resource
    private Executor taskExecutor;

    /**
     * 任务一和任务二执行完成后,再执行任务三，接收任务一二的结果作为参数,有返回值
     */
    @GetMapping("/test01")
    public void test01() {
        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            log.info("任务A线程：" + Thread.currentThread().getName());
            return "hello";
        }, taskExecutor);

        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            log.info("任务B线程：" + Thread.currentThread().getName());
            return "world";
        }, taskExecutor);

        CompletableFuture<String> futureC = futureA.thenCombine(futureB, (AResult, BResult) -> {
            log.info("执行任务C结果" + AResult + " " + BResult + "，任务C线程：" + Thread.currentThread().getName());
            return AResult + " " + BResult;
        });
        log.info("futureC.join():{}", futureC.join());
    }

    /**
     * thenCompose 任务一执行完成后，将任务一的结果
     * 和thenApply的区别  thenApply适用于数据的映射转换，thenCompose用于链接2个异步任务
     */
    @GetMapping("/test02")
    public void test02() throws ExecutionException, InterruptedException {
        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            log.info("任务A线程：" + Thread.currentThread().getName());
            return "hello";
        }, taskExecutor);

        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            log.info("任务B线程：" + Thread.currentThread().getName());
            return "world";
        }, taskExecutor);

        CompletableFuture<String> futureC = futureA.thenCompose((AResult) -> {
            return futureB.thenApply((BResult) -> {
                return AResult + " " + BResult;
            });
        });
        log.info("futureC.get():{}",futureC.get());
    }

    /**
     * thenApply 如果链接两个CompletableFuture异步任务，会存在CompletableFuture的嵌套
     * 如果使用thenApply链接两个异步任务，存在CompletableFuture的嵌套
     */
    @GetMapping("/test03")
    public void test03() throws ExecutionException, InterruptedException {
        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            log.info("任务A线程：" + Thread.currentThread().getName());
            return "hello";
        }, taskExecutor);

        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            log.info("任务B线程：" + Thread.currentThread().getName());
            return "world";
        }, taskExecutor);

        CompletableFuture<CompletableFuture<String>> futureC = futureA.thenApply((AResult) -> {
            return futureB.thenApply((BResult) -> {
                return AResult + " " + BResult;
            });
        });
        log.info("futureC.get().get():{}",futureC.get().get());
    }
}
